package elicecn.media.vox;

//6000Hz/8bit PCM Wave文件头
public class WaveHeader {
	private static final int HEADER_BYTES = 44;
	private static final int RIFF_BYTES = 8;
	// 00H 4 char "RIFF" char riff_id[4]="RIFF"
	byte[] riff = { 'R', 'I', 'F', 'F' };
	// 04H 4 long int 文件总长-8 long int size0=文总长-8
	int fileLength;
	// 08H 8 char "WAVEfmt " char wave_fmt[8]
	byte[] wavefmt = { 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ' };
	// 10H 4 long int 10 00 00 00H(PCM) long int size1=0x10
	int fmtSize = 0x10;

	// ==== fmt content ====
	// 14H 2 int 01 00H int fmttag=0x01
	short fmttag = 0x01;// PCM格式
	// 16H 2 int int channel=1 或2
	short channcel = 1;
	// 18H 4 long int 采样率 long int samplespersec
	int samplePerSec = 6000;
	// 1CH 4 long int 每秒播放字节数 long int bytepersec
	int bytePerSec = 6000;
	// 20H 2 int 采样一次占字节数 int blockalign=声道数*量化数/8
	short blockAlign = 1;
	// 22H 2 int 量化数 int bitpersamples=8或16
	short bitPerSamples = 8;// 采样位数

	// 24H 4 char "data" char data_id="data"
	byte[] data = { 'd', 'a', 't', 'a' };
	// 28H 4 long int 采样数据字节数 long int size2=文长-44
	int dataLength;

	public WaveHeader(int dataBytes) {
		this.fileLength = HEADER_BYTES - RIFF_BYTES + dataBytes;
		this.dataLength = dataBytes;
	}

	public byte[] getBytes() {
		byte[] bytes = new byte[44];
		copyOf(riff, 0x0, 4, bytes);
		copyOf(int2ByteArray(fileLength), 0x4, 4, bytes);
		copyOf(wavefmt, 0x8, 8, bytes);
		copyOf(int2ByteArray(fmtSize), 0x10, 4, bytes);

		copyOf(short2ByteArray(fmttag), 0x14, 2, bytes);
		copyOf(short2ByteArray(channcel), 0x16, 2, bytes);
		copyOf(int2ByteArray(samplePerSec), 0x18, 4, bytes);
		copyOf(int2ByteArray(bytePerSec), 0x1c, 4, bytes);
		copyOf(short2ByteArray(blockAlign), 0x20, 2, bytes);
		copyOf(short2ByteArray(bitPerSamples), 0x22, 2, bytes);

		copyOf(data, 0x24, 4, bytes);
		copyOf(int2ByteArray(dataLength), 0x28, 4, bytes);

		return bytes;
	}

	/**
	 * byte数组复制
	 * 
	 * @param source
	 *            源数组
	 * @param fromIndex
	 *            开始下标
	 * @param size
	 *            复数字节数
	 * @param dest
	 *            目标数组
	 */
	public void copyOf(byte[] source, int fromIndex, int size, byte[] dest) {
		for (int i = fromIndex; i < fromIndex + size; i++) {
			dest[i] = source[i - fromIndex];
		}
	}

	// Little-Endian 低位在前，高位在后
	public byte[] int2ByteArray(int v) {
		byte[] result = new byte[4];
		for (int i = 0; i < 4; i++) {
			result[i] = (byte) ((v >>> (i * 8)) & 0xff);
		}
		return result;
	}

	// Little-Endian 低位在前，高位在后
	public byte[] short2ByteArray(short v) {
		byte[] result = new byte[2];
		for (int i = 0; i < 2; i++) {
			result[i] = (byte) ((v >>> (i * 8)) & 0xff);
		}
		return result;
	}
}
